package community.hospital.service.application.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import community.hospital.common.CustomerException;
import community.hospital.common.LoginUserHolder;
import community.hospital.convert.OrderConvert;
import community.hospital.convert.PageConvert;
import community.hospital.entity.Order;
import community.hospital.entity.request.ListOrderRequest;
import community.hospital.entity.request.OrderRequest;
import community.hospital.entity.response.*;
import community.hospital.service.application.DepartmentApplicationService;
import community.hospital.service.application.OrderApplicationService;
import community.hospital.service.application.ScheduleApplicationService;
import community.hospital.service.application.UserApplicationService;
import community.hospital.service.domain.OrderService;
import community.hospital.util.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;

import static community.hospital.common.RedisConstant.SPLIT;
import static community.hospital.enums.BusinessEnum.ORDER_REPEAT;
import static community.hospital.enums.BusinessEnum.REMAINING_QUANTITY_INSUFFICIENT;

/**
 * @author yindingjie
 */
@Service
public class OrderApplicationServiceImpl implements OrderApplicationService {
    @Resource
    private OrderService orderService;
    @Resource
    private ScheduleApplicationService scheduleApplicationService;
    @Resource
    private UserApplicationService userApplicationService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private HospitalApplicationServiceImpl hospitalApplicationService;
    @Resource
    private DepartmentApplicationService departmentApplicationService;

    @Override
    public Boolean addOrder(OrderRequest request) {
        Order order = OrderConvert.INSTANCE.convertToOrder(request);
        ScheduleResponse scheduleResponse = scheduleApplicationService.querySchedule(request.getScheduleId());
        Long userId = LoginUserHolder.getUser().getId();
        order.setUserId(userId);
        //判断用户是否挂过当天该医生的号
        String key = String.join(SPLIT, "order", userId.toString(), scheduleResponse.getId().toString(),LocalDate.now(ZoneId.systemDefault()).toString());
        if (redisUtil.incr(key)>1) {
            throw new CustomerException(ORDER_REPEAT);
        }
        redisUtil.expire(key,24*60*60L);
        //当天的号源数量
        Integer registerQuantity = scheduleResponse.getDoctorResponse().getRegisterQuantity();
        key = String.join(SPLIT, "order", scheduleResponse.getId().toString(), LocalDate.now(ZoneId.systemDefault()).toString());
        int count = redisUtil.incr(key).intValue();
        if (count > registerQuantity) {
            throw new CustomerException(REMAINING_QUANTITY_INSUFFICIENT);
        }
        redisUtil.expire(key,24*60*60L);
        //保存订单
        boolean isOk = orderService.save(order);
        //TODO 消息队列30分钟为支付取消功能实现（为支付redis中的号源数量需要减一）
        return isOk;
    }

    @Override
    public Boolean updateOrderState(Long orderId, Integer state) {
        return orderService.updateOrderState(orderId, state);
    }

    @Override
    public Page<OrderResponse> listOrder(ListOrderRequest request) {
        Page<Order> page = orderService.listOrder(request);
        Page<OrderResponse> orderResponsePage = PageConvert.convert(page, OrderConvert.INSTANCE::convertToResp);
        for (int i = orderResponsePage.getRecords().size() - 1; i >= 0; i--) {
            Order order = page.getRecords().get(i);
            OrderResponse orderResponse = orderResponsePage.getRecords().get(i);
            handleOrderResponse(order, orderResponse);
        }
        return orderResponsePage;
    }

    @Override
    public int countByScheduleId(Long scheduleId) {
        return orderService.countByScheduleId(scheduleId).intValue();
    }

    @Override
    public IPage<OrderDetailResp> getCurrentUserOrder() {
        UserResponse userResponse = LoginUserHolder.getUser();
        //根据当前用户id查询订单
        ListOrderRequest listOrderRequest = new ListOrderRequest(1,100);

        listOrderRequest.setUserId(userResponse.getId());
        IPage<OrderDetailResp> page = listOrder(listOrderRequest).convert(orderResponse -> {
            return toOrderDetail(orderResponse, userResponse.getId());
        });
        ListIterator<OrderDetailResp> iterator = page.getRecords().listIterator();
        //获取当前时间的年月日
        Calendar calendar = Calendar.getInstance();
        int weekYear = calendar.getWeekYear();
        int month = calendar.get(Calendar.MONTH) + 1;
        int date = calendar.get(Calendar.DAY_OF_MONTH);
        ArrayList<OrderDetailResp> list = new ArrayList<>();
        while (iterator.hasNext()) {
            OrderDetailResp next = iterator.next();
            if (next.getYear()==weekYear && next.getMonth()==month&& next.getDay()==date) {
                iterator.remove();
                list.add(next);
            }
        }
        list.sort(Comparator.comparingInt(OrderDetailResp::getScheduleCode));
        page.getRecords().addAll(0, list);

        return page;
    }

    @Override
    public OrderDetailResp getRecentlyOrder() {
        UserResponse user = LoginUserHolder.getUser();
        Order order = orderService.getAfterTomorrowOrder(user.getId());
        OrderResponse orderResponse = OrderConvert.INSTANCE.convertToResp(order);
        handleOrderResponse(order, orderResponse);
        return toOrderDetail(orderResponse, user.getId());
    }

    public OrderResponse getOrderByUserId(Long id) {
        //根据用户id查询订单
        return null;

    }
    //获取当前用户的排号顺序
    private int getRank(Long scheduleId,Long userId){
        return orderService.getRank(scheduleId, userId);
    }

    private OrderResponse handleOrderResponse(Order order,OrderResponse orderResponse) {
        Long scheduleId = order.getScheduleId();
        ScheduleResponse scheduleResponse = scheduleApplicationService.querySchedule(scheduleId);
        Long userId = order.getUserId();
        UserResponse userResponse =  userApplicationService.queryByUserId(userId);
        orderResponse.setScheduleResponse(scheduleResponse);
        orderResponse.setUserResponse(userResponse);
        return orderResponse;
    }

    private OrderDetailResp toOrderDetail(OrderResponse orderResponse,Long userId) {
        ScheduleResponse scheduleResponse = orderResponse.getScheduleResponse();
        String doctorName = scheduleResponse.getDoctorResponse().getName();
        Long hospitalId = scheduleResponse.getHospitalId();
        Long department1Id = scheduleResponse.getDepartment1Id();
        Long department2Id = scheduleResponse.getDepartment2Id();
        HospitalResponse hospital = hospitalApplicationService.getHospital(hospitalId);
        String hospitalName = hospital.getName();
        String dept1Name = departmentApplicationService.queryById(department1Id).getDeptName();
        String dept2Name = departmentApplicationService.queryById(department2Id).getDeptName();
        OrderDetailResp orderDetailResp = new OrderDetailResp();
        BeanUtils.copyProperties(scheduleResponse, orderDetailResp);
        orderDetailResp.setHospitalName(hospitalName).setDepartment1Name(dept1Name).setDepartment2Name(dept2Name).setDoctorName(doctorName);
        int rank = getRank(scheduleResponse.getId(), userId);
        orderDetailResp.setRank(rank);
        orderDetailResp.setAddress(hospital.getAddress());
        return orderDetailResp;
    }

}
